﻿using System;
using System.Drawing;
using System.Windows.Forms;
using System.Collections;
namespace eightnum
{
    public partial class EiNumForm1 : Form
    {
        private int progress;
        private int demo;
        private Button[,] buttonElemS;
        private Button[,] buttonElemD;
        /// <summary>
        /// 源8数码表
        /// </summary>
        private int[,] sTable;
        public int[,] STable
        {
            get
            {
                return sTable;
            }
            set
            {
                sTable = value;
            }
        }
        /// <summary>
        /// 目标8数码表
        /// </summary>
        private int[,] dTable;
        /// <summary>
        /// 能自动产生随机数的棋盘
        /// </summary>
        private Generation gen;
        public Generation Gen 
        {
            get
            {
                return gen;
            }
            set
            {
                gen = value;
            }
        }
        private ArrayList Result=new ArrayList(); 


        /// <summary>
        /// 构造函数
        /// 初始化,创建棋盘,产生随机数
        /// </summary>
        public EiNumForm1()
        {
            InitializeComponent();//初始化窗口
            label2.BackColor =Color.Transparent;
        #region 目标8数码表赋值
            dTable = new int[3, 3];
            dTable[0, 0] = 1; dTable[0, 1] = 2; dTable[0, 2] = 3;
            dTable[1, 0] = 8; dTable[1, 1] = 0; dTable[1, 2] = 4; 
            dTable[2, 0] = 7; dTable[2, 1] = 6; dTable[2, 2] = 5;
        #endregion
            buttonElemS=CreatePan(10, 12,true,groupBox1);//初始化初始棋盘
            GenerationRandom();//给初始棋盘赋值
            buttonElemD= CreatePan(10, 12, false, groupBox2);//初始化目标棋盘
            UpdatePan(buttonElemD,dTable);


        }

        /// <summary>
        /// 创建棋盘
        /// </summary>
        /// <param name="x">从横坐标的什么位置开始创建</param>
        /// <param name="y">从纵坐标的什么位置开始创建</param>
        public Button[,] CreatePan(int x, int y,bool changAble,GroupBox groupBox)
        {
            Button [,] buttonElem=new Button[3,3];
            int []a;
            Font font = new Font(new FontFamily(this.Font.Name), 36f, FontStyle.Bold);
            for (int i = 0; i < 3; i++)
                for (int j = 0; j < 3; j++)
                {
                    a=new int[2];
                    a[0] = i;
                    a[1] = j;
                    
                    buttonElem[i, j] = new Button();
                    buttonElem[i, j].FlatStyle = System.Windows.Forms.FlatStyle.Flat;
                    buttonElem[i, j].BackgroundImage = global::eightnum.Properties.Resources.num;
                    buttonElem[i, j].Size = new Size(62, 62);
                    buttonElem[i, j].Location = new Point(j * 63 + x, i * 63 + y);
                    buttonElem[i, j].Text = " ";
                    buttonElem[i, j].Font = font;
                    buttonElem[i, j].Tag=a;
                    groupBox.Controls.Add(buttonElem[i, j]);
                    buttonElem[i, j].TextChanged += new System.EventHandler(this.button2_TextChanged);
                    buttonElem[i, j].Text = "";
                    if(changAble)
                        buttonElem[i, j].Click += new EventHandler(EiNumForm1_Click);
                }
            return buttonElem;

        }
        
        /// <summary>
        /// 更新棋盘
        /// </summary>
        public void UpdatePan(Button [,] buttonElem,int [,] table) 
        {
            for (int i = 0; i < 3; i++)
                for (int j = 0; j < 3; j++)
                {
                    if (table[i, j] != 0)
                        buttonElem[i, j].Text = table[i, j].ToString();
                    else
                        buttonElem[i, j].Text = ""; 
                }
        }

        /// <summary>
        /// 判断位置是否存在
        /// </summary>
        /// <param name="i">第i行</param>
        /// <param name="j">第j列</param>
        /// <returns></returns>
        private bool posIsExist(int i,int j)
        {
            if (i < 0 || i > 2 || j < 0 || j > 2)
                return false;
            else return true;
        }

       
        /// <summary>
        /// 点击按钮时移动
        /// </summary>
        /// <param name="OPosx">行</param>
        /// <param name="OPosy">列</param>
        /// <returns></returns>
        public bool MoveButton(int OPosx,int OPosy)
        {
            int temp;
            if (sTable[OPosx, OPosy] == 0)
                return false;
            else 
            {
                int []a=new int[3];
                a[0] = -1;
                a[1] = 0;
                a[2] = 1;
                foreach(int i in a)
                    foreach (int j in a)
                    {
                        if(i*j==0&&!(i==0&&j==0))
                           if (posIsExist(OPosx + i, OPosy + j))
                             if (sTable[OPosx + i, OPosy + j] == 0)
                                {
                                    temp = sTable[OPosx + i, OPosy + j];
                                    sTable[OPosx + i, OPosy + j] = sTable[OPosx, OPosy];
                                    sTable[OPosx, OPosy] = temp;
                                    return true;
                                }
                    }
                return false;
            }
        }
        /// <summary>
        /// 产生随机数的函数,自动判断是否有解
        /// </summary>
        private void GenerationRandom()
        {
            gen = new Generation();
            gen.GenRandom();
            STable = gen.Table;
            for (int i = 0; i < 3; i++)
                for (int j = 0; j < 3; j++)
                {
                    if (sTable[i, j] != 0)
                        buttonElemS[i, j].Text = sTable[i, j].ToString();
                    else
                    {
                        buttonElemS[i, j].Text = "";
                    }
                }
            if (HasTheAnswer())
                label2.Text = "有解";
            else
                label2.Text = "无解";
        }
        /// <summary>
        /// 通过判断逆序数的奇偶性判断是否有解
        /// </summary>
        /// <returns></returns>
        public bool HasTheAnswer() 
        { int s=0,d=0;//源，目标的
            for(int i=0;i<9;i++)
                for (int j = 0; j < i; j++)
                {
                    if ((sTable[j / 3, j % 3] > sTable[i / 3, i % 3]) && (sTable[i / 3, i % 3]!=0))
                        s++;
                    if ((dTable[j / 3, j % 3] > dTable[i / 3, i % 3]) && (dTable[i / 3, i % 3] != 0))
                        d++;
                }
            if (s%2 == d%2) return true;
            else return false;
        }
        /// <summary>
        /// 点击产生随机数的事件，并判断是否有解
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void 产生随机数button_Click(object sender, EventArgs e)
        {
            //#region 课本数据测试
            //sTable[0, 0] = 2; sTable[0, 1] = 8; sTable[0, 2] = 3;
            //sTable[1, 0] = 1; sTable[1, 1] = 0; sTable[1, 2] = 4;
            //sTable[2, 0] = 7; sTable[2, 1] = 6; sTable[2, 2] = 5;
            //UpdatePan(buttonElemS, sTable);
            //if (HasTheAnswer())
            //    label2.Text = "有解";
            //else
            //    label2.Text = "无解";
            //#endregion
            //#region 数据测试2
            //sTable[0, 0] = 1; sTable[0, 1] = 2; sTable[0, 2] = 3;
            //sTable[1, 0] = 8; sTable[1, 1] = 0; sTable[1, 2] = 4;
            //sTable[2, 0] = 7; sTable[2, 1] = 6; sTable[2, 2] = 5;
            //UpdatePan(buttonElemS, sTable);
            //if (HasTheAnswer())
            //    label2.Text = "有解";
            //else
            //    label2.Text = "无解";
            //#endregion
            GenerationRandom();
            #region 目标状态重置
            dTable[0, 0] = 1; dTable[0, 1] = 2; dTable[0, 2] = 3;
            dTable[1, 0] = 8; dTable[1, 1] = 0; dTable[1, 2] = 4; 
            dTable[2, 0] = 7; dTable[2, 1] = 6; dTable[2, 2] = 5;
            #endregion
            button3.Enabled = true;
        }
        /// <summary>
        /// 点击移动数码的事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void EiNumForm1_Click(object sender, EventArgs e)
        {
            int []a=(int[])((Button)sender).Tag;
            MoveButton(a[0], a[1]);
            UpdatePan(buttonElemS,sTable);
           
        }

        private void 求解button_Click(object sender, EventArgs e)
        {
            #region 目标状态重置
            dTable[0, 0] = 1; dTable[0, 1] = 2; dTable[0, 2] = 3;
            dTable[1, 0] = 8; dTable[1, 1] = 0; dTable[1, 2] = 4;
            dTable[2, 0] = 7; dTable[2, 1] = 6; dTable[2, 2] = 5;
            #endregion
            listBox1.Items.Clear();
            Result.Clear();
            #region 之前较差的算法
            //if (label2.Text == "有解")
            //{
            //    Algorithm A = new Algorithm();
            //    Algorithm.node node1 = new Algorithm.node();
            //    node1.table = (int[,])sTable.Clone();
            //    for (int i = 0; i < 3; i++)
            //        for (int j = 0; j < 3; j++)
            //            if (sTable[i, j] == 0) node1.pos = i * 3 + j;

            //    Algorithm.node nodeResult = A.extentSearch(node1, dTable);
            //    //  UpdatePan(buttonElemD, ((Algorithm.node)nodeResult.nodeparent).table);
            //    listBox1.Items.Add("总:" + A.validNodeNum.ToString());
            //    Algorithm.node n = nodeResult;
            //    int k = 0;
            //    while (n.nodeparent != null)
            //    {
            //        n = (Algorithm.node)n.nodeparent;
            //        k++;
            //    }
            //    listBox1.Items.Add(k);
            //}
            //else {
            //    listBox1.Items.Add("无解还没做哦");
            //}
            #endregion

            #region 有错误的算法,哎
            /*
            int[] stemptable = new int[9];
            int[] dtemptable = new int[9];
          
            int maxDepth = 0;
            //检查输入的深度是否为数字
            try
            {
                maxDepth = int.Parse(Maxdepth.Text);
            }
            catch
            {
                MessageBox.Show("最佳深度只能为数字");
                return;
            }
            
            //将表盘转为一位表
            for(int i=0;i<3;i++)
                for (int j = 0; j < 3; j++)
                {
                    stemptable[i * 3 + j] = sTable[i, j];
                    dtemptable[i * 3 + j] = dTable[i, j];
                }
            
            AIcores1 Ai=new AIcores1();
            Answer ans = Ai.Compute(stemptable, dtemptable, int.Parse(Maxdepth.Text), radioButton1.Checked);

            if (ans == Answer.Exist)
            {
                listBox1.Items.Add("求解结果：");
                Result = Ai.Result;
                if (Result == null || Result.Length == 0)
                {
                    listBox1.Items.Add("不需要移动哦");
                    return;
                }
                listBox1.Items.Add("需要移动的步数为："+Ai.Result.Length);
                 for (int i = 0; i < Result.Length; i++)
                {
                    if (Ai.Result[i] != Direction.None)
                       listBox1.Items.Add("第" + (i + 1) + "步移向: " + Ai.Result[i]);
                }
            }
            else if (ans == Answer.NotExistInDepth)
            {
                listBox1.Items.Add("在深度为\"" + Maxdepth.Text + "\"的范围内找不到解!");
            }
            else
            {
                listBox1.Items.Add("无解哦");
                return;
            }
           listBox1.Items.Add("搜索结点数:" + Ai.Nodes);
           listBox1.Items.Add("有效结点个数:" + Ai.Result.Length + "个!");
           button2.Enabled = true;
             */
            #endregion
            if (label2.Text == "无解") {
                listBox1.Items.Add("无解哦，嘎嘎");
                button2.Enabled = false;
                return;
            }
            AIcores Ai = new AIcores();
            if (radioButton2.Checked == true)
            {
                if (Ai.Ax(sTable, dTable, int.Parse(Maxdepth.Text)) == 2)
                {
                    for (int i = Ai.result.Count; i > 0; i--)
                    {
                        Result.Add(Ai.result[i - 1]);
                        listBox1.Items.Add("移动方向：" + ((Node)Ai.result[i - 1]).dir.ToString());
                    }
                    listBox1.Items.Add("一共:" + Result.Count.ToString() + "步");
                    button2.Enabled = true;
                }
                else
                {
                    listBox1.Items.Add("无解哦");
                }
            }
            else
            {
                if (Ai.broad(sTable, dTable, int.Parse(Maxdepth.Text)) == 2)
                {
                    for (int i = Ai.result.Count; i > 0; i--)
                    {
                        Result.Add(Ai.result[i - 1]);
                        listBox1.Items.Add("移动方向：" + ((Node)Ai.result[i - 1]).dir.ToString());
                    }
                    listBox1.Items.Add("一共:" + Result.Count.ToString() + "步");
                    button2.Enabled = true;
                }
                else
                {
                    listBox1.Items.Add("无解哦");
                }
            }
            listBox1.Items.Add("总共访问结点：" + Ai.nodes + "个");
        }

        private void button2_Click(object sender, EventArgs e)
        {
            demo = 0;
            timer1.Enabled = true;
        }


        private void timer1_Tick_1(object sender, EventArgs e)
        {
            string temp = "";
            int[,] temptable = new int[3, 3];

            if (demo < Result.Count)
            {
                int pos = ((Node)Result[demo]).code % 10 - 1;
                temp = ((Node)Result[demo]).code.ToString();
                for (int i = 0; i < pos; i++)
                {
                    temptable[i / 3, i % 3] = int.Parse(temp[i].ToString());
                }
                temptable[pos / 3, pos % 3] = 0;
                for (int i = pos + 1; i < 9; i++)
                {
                    temptable[i / 3, i % 3] = int.Parse(temp[i - 1].ToString());
                }
                UpdatePan(buttonElemD, temptable);
                demo++;

            }
            else
            {
                timer1.Enabled = false;
                button3.Enabled = true;
            }
        }

        private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
        {
            timer1.Enabled = false;
            demo = 0;
            string temp = "";
            int[,] temptable = new int[3, 3];
            if (listBox1.SelectedIndex < 0) return;
            if (listBox1.SelectedIndex < Result.Count)
            {
                int pos = ((Node)Result[listBox1.SelectedIndex]).code % 10 - 1;
                temp = ((Node)Result[listBox1.SelectedIndex]).code.ToString();
                for (int i = 0; i < pos; i++)
                {
                    temptable[i / 3, i % 3] = int.Parse(temp[i].ToString());
                }
                temptable[pos / 3, pos % 3] = 0;
                for (int i = pos + 1; i < 9; i++)
                {
                    temptable[i / 3, i % 3] = int.Parse(temp[i - 1].ToString());
                }
                UpdatePan(buttonElemD, temptable);
            }
        }

        private void button2_TextChanged(object sender, EventArgs e)
        {
            if(((Button)sender).Text=="")
                ((Button)sender).Visible = false;
            else
                ((Button)sender).Visible = true ;
        }


    }




    }
